﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using HPAGMRestAPIWrapper;
using AGMLite.BaseClass;
using System.Reflection;
using System.Collections;
using System.Windows;
using AGMLite.Windows;
using System.Windows.Threading;

namespace AGMLite.ViewModelClass
{
    public class ProjectViewModel : ViewModelBase
    {
        #region Properties
        public AGMProject Project
        {
            get
            {
                return _project;
            }
            set
            {
                if (value != _project)
                {
                    _project = value;
                    OnPropertyChanged("Project");
                }
            }
        }

        public AGMItem SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                if (value != _selectedItem)
                {
                    _selectedItem = value;
                    OnPropertyChanged("SelectedItem");
                }
            }
        }
        public bool IsRequireReconnect { get; set; }
        public bool IsCancel { get; set; }
        #endregion

        #region Private members
        private AGMProject _project;
        private AGMProject _clonedProject;
        private AGMItem _selectedItem;
        private List<string> _changedFields;

        private RelayCommand<object> saveCommand;
        private RelayCommand<object> cancelCommand;
        private RelayCommand<object> openFileCommand;

        private RelayCommand<object> addItemCommand;
        private RelayCommand<object> deleteItemCommand;
        private RelayCommand<object> editItemCommand;
        private RelayCommand<object> syncItemCommand;
        private RelayCommand<object> viewEntityListCommand;
        #endregion

        public ProjectViewModel(AGMProject project)
        {
            _changedFields = new List<string>();
            _clonedProject = project.ShallowCopy();

            Project = project;
            Project.PropertyChanged += PropertyChangedHandler;
        }

        public void CloneProject()
        {
            _clonedProject = Project.ShallowCopy();
        }

        public void PropertyChangedHandler(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("message", StringComparison.InvariantCultureIgnoreCase) ||
                e.PropertyName.Equals("status", StringComparison.InvariantCultureIgnoreCase))
                return;

            if (!_changedFields.Contains(e.PropertyName))
                _changedFields.Add(e.PropertyName);

            if (e.PropertyName.Equals("server", StringComparison.InvariantCultureIgnoreCase) || 
                e.PropertyName.Equals("username", StringComparison.InvariantCultureIgnoreCase) ||
                e.PropertyName.Equals("password", StringComparison.InvariantCultureIgnoreCase) ||
                e.PropertyName.Equals("project", StringComparison.InvariantCultureIgnoreCase) ||
                e.PropertyName.Equals("domain", StringComparison.InvariantCultureIgnoreCase))
            {
                IsRequireReconnect = true;
            }
        }

        #region Commands
        public System.Windows.Input.ICommand SaveCommand
        {
            get
            {
                if (saveCommand == null)
                {
                    saveCommand = new RelayCommand<object>(x => this.Save(x), x => this.CanSave());
                }
                return saveCommand;
            }
        }

        public System.Windows.Input.ICommand CancelCommand
        {
            get
            {
                if (cancelCommand == null)
                {
                    cancelCommand = new RelayCommand<object>(x => this.Cancel(x), x => this.CanCancel());
                }
                return cancelCommand;
            }
        }

        public System.Windows.Input.ICommand OpenFileCommand
        {
            get
            {
                if (openFileCommand == null)
                {
                    openFileCommand = new RelayCommand<object>(x => this.OpenFile(), x => this.CanOpenFile());
                }
                return openFileCommand;
            }
        }

        public System.Windows.Input.ICommand AddItemCommand
        {
            get
            {
                if (addItemCommand == null)
                {
                    addItemCommand = new RelayCommand<object>(x => this.AddItem(), x => this.CanAddItem());
                }
                return addItemCommand;
            }
        }

        public System.Windows.Input.ICommand DeleteItemCommand
        {
            get
            {
                if (deleteItemCommand == null)
                {
                    deleteItemCommand = new RelayCommand<object>(x => this.DeleteItem(x), x => this.CanDeleteItem(x));
                }
                return deleteItemCommand;
            }
        }

        public System.Windows.Input.ICommand EditItemCommand
        {
            get
            {
                if (editItemCommand == null)
                {
                    editItemCommand = new RelayCommand<object>(x => this.EditItem(x), x => this.CanEditItem(x));
                }
                return editItemCommand;
            }
        }

        public System.Windows.Input.ICommand SyncItemCommand
        {
            get
            {
                if (syncItemCommand == null)
                {
                    syncItemCommand = new RelayCommand<object>(x => this.SyncItem(x), x => this.CanSyncItem(x));
                }
                return syncItemCommand;
            }
        }

        public System.Windows.Input.ICommand ViewEntityListCommand
        {
            get
            {
                if (viewEntityListCommand == null)
                {
                    viewEntityListCommand = new RelayCommand<object>(x => this.ViewEntityList(x), x => this.CanViewEntityList(x));
                }
                return viewEntityListCommand;
            }
        }
        #endregion

        #region Implementation
        public void Save(object obj)
        {
            if (string.IsNullOrEmpty(Project.GUID))
                Project.GUID = Guid.NewGuid().ToString();
            Project.Save(false);
            IsCancel = false;
            Window win = obj as Window;
            win.Close();
        }

        public void Cancel(object obj)
        {
            IsCancel = true;
            Window win = obj as Window;
            win.Close();
        }

        public void OpenFile()
        {
            string file = null;
            System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
            ofd.Title = "Select a picture for project";
            ofd.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
                "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
                "Portable Network Graphic (*.png)|*.png";
            ofd.Multiselect = false;

            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                file = ofd.FileName;
                if (!System.IO.Directory.Exists(System.IO.Path.Combine(Common.ApplicationSetting.SettingStoreFolder, "ProjectIcons")))
                    System.IO.Directory.CreateDirectory(System.IO.Path.Combine(Common.ApplicationSetting.SettingStoreFolder, "ProjectIcons"));

                System.IO.File.Copy(file, System.IO.Path.Combine(Common.ApplicationSetting.SettingStoreFolder, "ProjectIcons", System.IO.Path.GetFileName(file)), true);
                Project.Icon = System.IO.Path.GetFileName(file);
            }
        }

        public void AddItem()
        {
            AGMItem newItem = new AGMItem()
            {
                Project = Project,
                Name = "New Item",
                CanEditEntityType = true,
                IsEnabled = true,
                SyncInterval = 300,
                FilterFieldCollection = new ObservableCollectionEx<AGMLiteEntityFilterField>(),
                ViewFieldCollection = new ObservableCollectionEx<AGMLiteEntityViewField>(),
                EntityType = Common.AGMLiteEnum.EntityType.Requirement,
                LiteEntityCollection = new ObservableCollectionEx<AGMLiteEntity>(),
            };

            ItemViewModel newIVM = new ItemViewModel(newItem);
            OpenItemEditWindow(newIVM);
            if (!string.IsNullOrEmpty(newItem.GUID))
            {
                newItem.StartTimer();
                newItem.IsSyncImmediatelly = true;
                Project.ItemCollection.Add(newItem);
                newItem.UpdateAllFields(); 
                if (newItem.IsRequireSync)
                {
                    newItem.Sync();
                    newItem.IsRequireSync = false;
                }
            }
        }

        public void EditItem(object obj)
        {
            if (obj != null)
            {
                AGMItem selectedItem = (AGMItem)obj;
                ItemViewModel selectedItemVM = new ItemViewModel(selectedItem);
                selectedItemVM.Item.CanEditEntityType = false;                
                OpenItemEditWindow(selectedItemVM);

                if (selectedItem.IsRequireSync)
                {
                    if (!selectedItem.IsEnabled)
                        selectedItem.Status = 4;
                    selectedItem.IsSyncImmediatelly = true;
                    selectedItem.Sync();
                    selectedItem.IsRequireSync = false;
                }
            }
        }

        public void DeleteItem(object obj)
        {
            if (obj != null)
            {
                AGMItem selectedItem = (AGMItem)obj;

                string Message = null;

                Message = "Are you sure to delete the item?";

                MessageBoxResult result = MessageBox.Show(Message, "Delete Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question);
                if (result == MessageBoxResult.Yes)
                {
                    Project.ItemCollection.Remove(selectedItem);
                    selectedItem.Save(true);
                }
            }
        }

        public void SyncItem(object obj)
        {
            if (obj != null)
            {
                AGMItem selectedItem = (AGMItem)obj;
                selectedItem.IsSyncImmediatelly = true;
                selectedItem.Sync();
            }
        }

        public void ViewEntityList(object obj)
        {
            if (obj != null)
            {
                AGMItem selectedItem = (AGMItem)obj;

                EntityListViewModel entitiesVM = new EntityListViewModel(selectedItem);
                EntityListWindow entitylistWindow = new EntityListWindow();
                entitylistWindow.DataContext = entitiesVM;
                entitylistWindow.WindowStartupLocation = WindowStartupLocation.Manual;
                if (entitiesVM.CloseAction == null) entitiesVM.CloseAction = new Action(() => entitylistWindow.Close());
                entitylistWindow.ShowDialog();
            }
        }

        public bool CanAddItem()
        {
            if (Project.Status == 2)
                return true;

            return false;
        }

        public bool CanDeleteItem(object obj)
        {
            if (obj == null)
                return false;

            AGMItem selectedItem = obj as AGMItem;
            if (selectedItem.Status != 3)
                return true;

            return false;
        }

        public bool CanEditItem(object obj)
        {
            if (Project.Status == 2 && obj != null)
                return true;

            return false;
        }

        public bool CanSyncItem(object obj)
        {
            if (obj == null)
                return false;

            AGMItem selectedItem = obj as AGMItem;
            if (selectedItem.Status != 3 && Project.Connection !=null)
                return true;

            return false;
        }

        public bool CanViewEntityList(object obj)
        {
            if (obj == null)
                return false;

            AGMItem selectedItem = obj as AGMItem;
            if (selectedItem.Status == 0 || selectedItem.Status == 2)
            {
                if (selectedItem.LiteEntityCollection.Count == 0)
                    return false;
                else
                    return true;
            }
            else
            {
                return false;
            }
        }

        public bool CanSave()
        {
            return string.IsNullOrEmpty(Project.Error);
        }

        public bool CanCancel()
        {
            return true;
        }

        public bool CanOpenFile()
        {
            return true;
        }

        public void RollBackChanges()
        {
            if (_clonedProject != null)
            {
                foreach (string field in _changedFields)
                {
                    PropertyInfo piCurrent = Project.GetType().GetProperty(field);
                    PropertyInfo piSaved = _clonedProject.GetType().GetProperty(field);
                    piCurrent.SetValue(Project, piSaved.GetValue(_clonedProject, null), null);
                }

                IsRequireReconnect = false;
            }
        }
        #endregion

        #region Private Methods

        private ItemViewModel OpenItemEditWindow(ItemViewModel itemVM)
        {
            itemVM.Item.IsEditing = true;
            ItemEditWindow itemEditWindow = new ItemEditWindow();
            itemEditWindow.DataContext = itemVM;
            itemEditWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            if (itemVM.CloseAction == null) itemVM.CloseAction = new Action(() => itemEditWindow.Close());
            itemEditWindow.ShowDialog();
            itemVM.Item.IsEditing = false;

            return itemVM;
        }
        #endregion

    }
}
